home *** CD-ROM | disk | FTP | other *** search
-
-
- L ZZZZZZ RRRRR SSSSS
- L Z R R S
- L aaa Z aaa R R u u S
- L a Z a RRRRR u u SSSSS
- XX L aaaa Z aaaa R R u u S
- XXXX L a a Z a a R R u u S
- XXXXXX LLLLLLL aaaaa ZZZZZZZ aaaaa R R uuuuu SSSSSS
- XXXXXX
- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- XXXXXX
- XXXXXX
- XXXX proudly presents his 23.Cracking Tutorial (06.07.1999)
- XX Cracking VB5 progs with W32Dasm
-
- I. Introduction
- II. The essay
- III. BTW
- IV. All Tutorials by LaZaRuS
-
- I. Welcome to my 23st cracking tutorial.
- Yep, I know: There's a handy little tool call Smartcheck. I tried to download it once, but
- I got a corrupted RAR file. D/l it again? Nah, not with my "turtle"-connection. I already
- have a disassembler and a debugger: W32Dasm and SICE. Actually there are some guys that
- say the only thing you get for VB progs in W32Dasm is garbage. *Completely* wrong. It's
- just a matter of interpretation. A VB5 prog in W32Dasm does (generally) look like a W32Asm
- prog without string references. The main difference is that VB progs are *easier* to crack.
- It seems obvious that VB coders use the predefined functions for the comparison of the
- good/bad serial. (and btw: razzia didn't have Smartcheck for his famous VB essay, too :P)
- As examples I take two CrackMe's of BuLLeT (1.75 and 2.75).
-
- I.1 W32Dasm 8.9
- BuLLeT's CrackMe 1.75
- BuLLeT's CrackMe 2.75
- Audio List Maker 1.52.1016
-
- II. The essay
- Let's start with the first CrackMe. When you disassemble it you will nothing but the
- functions that are called MSVBVM50.DLL.
-
- Import Module 001: MSVBVM50.DLL
- Addr:0F0399BC hint(0000) Name: _CIcos
- Addr:0F0E7F94 hint(0000) Name: _adj_fptan
- Addr:0F0E7855 hint(0000) Name: _adj_fdiv_m64
- Addr:0F0E7EDC hint(0000) Name: _adj_fprem1
- Addr:0F02B4EB hint(0000) Name: __vbaHresultCheckObj
- Addr:0F0E7809 hint(0000) Name: _adj_fdiv_m32
- Addr:0F01E2F2 hint(0000) Name: __vbaObjSet
- Addr:0F0E78A1 hint(0000) Name: _adj_fdiv_m16i
- Addr:0F0E79A1 hint(0000) Name: _adj_fdivr_m16i
- Addr:0F0399B2 hint(0000) Name: _CIsin
- Addr:0F01F90B hint(0000) Name: __vbaChkstk
- Addr:0F02299D hint(0000) Name: EVENT_SINK_AddRef
- Addr:0F01F8F6 hint(0000) Name: __vbaStrCmp
- Addr:0F0E7F91 hint(0000) Name: _adj_fpatan
- Addr:0F037FD1 hint(0000) Name: EVENT_SINK_Release
- Addr:0F0342BF hint(0000) Name: _CIsqrt
- Addr:0F03634A hint(0000) Name: EVENT_SINK_QueryInterface
- Addr:0F022B59 hint(0000) Name: __vbaExceptHandler
- Addr:0F0E7C24 hint(0000) Name: _adj_fprem
- Addr:0F0E7955 hint(0000) Name: _adj_fdivr_m64
- Addr:0F10A1A4 hint(0000) Name: __vbaFPException
- Addr:0F0342B5 hint(0000) Name: _CIlog
- Addr:0F0E78D5 hint(0000) Name: _adj_fdiv_m32i
- Addr:0F0E79D5 hint(0000) Name: _adj_fdivr_m32i
- Addr:0F0E7909 hint(0000) Name: _adj_fdivr_m32
- Addr:0F0E7344 hint(0000) Name: _adj_fdiv_r
- Addr:0F00A1BF hint(0064) Name: ThunRTMain
- Addr:0F0342AB hint(0000) Name: _CIatan
- Addr:0F0EA765 hint(0000) Name: _allmul
- Addr:0F0EA75B hint(0000) Name: _CItan
- Addr:0F01F2DD hint(0000) Name: _CIexp
- Addr:0F01F878 hint(0000) Name: __vbaFreeStr
- Addr:0F01DC7F hint(0000) Name: __vbaFreeObj
-
- Some of the names are selfexplaining, some of them are cryptic, but some of them have an
- interesting name: At least __vbaStrCmp - Doesn't it sound like StringCompare?
- Let's search for appearances in the deadlisting. The first one is obviously not the one
- that compares the good serial with the one you entered (Look at it and you'll see). The
- second (and last) one looks more interesting.
-
- * Referenced by a (U)nconditional or (C)onditional Jump at Address:
- |:004106D3(C)
- |
- :004106E6 FF75E8 push [ebp-18]
- :004106E9 6850014100 push 00410150
-
- * Reference To: MSVBVM50.__vbaStrCmp, Ord:0000h
- |
- :004106EE E8C509FFFF Call 004010B8
- :004106F3 8BD8 mov ebx, eax
- :004106F5 8D4DE8 lea ecx, dword ptr [ebp-18]
- :004106F8 F7DB neg ebx
- :004106FA 1BDB sbb ebx, ebx
- :004106FC 43 inc ebx
- :004106FD F7DB neg ebx
-
- Enter the debug mode of W32Dasm and set a breakpoint on :004106E9. Then trace into the
- next call. Tracing little further, you'll come to this:
-
- __vbaStrCmp()
- :0F01F8F6 push [esp+08]
- :0F01F8FA push [esp+08]
- :0F01F8FE push 00000000
- :0F01F900 call MSVBVM50.__vbaStrComp
- :0F01F905 movsx eax, ax
- :0F01F908 ret 0008
-
- MSVBVM50.__vbaStrComp? It's getting interesting, isn't it? Trace into this one, too.
-
- __vbaStrComp()
- :0F003563 push ebp
- :0F003564 mov ebp, esp
- :0F003566 push ebx
- :0F003567 push esi
- :0F003568 push edi
- :0F003569 cmp dword ptr [ebp+10], 00000000 // [ebp+10] points to the first string
- :0F00356D mov esi, 00000000
- :0F003572 je 0F00357A // if first string = "", then jump
- :0F003574 mov eax, dword ptr [ebp+10] //Here is the first string that is compared
- :0F003577 mov esi, dword ptr [eax-04] //ESI = Length(first string)*2
- :0F00357A cmp dword ptr [ebp+0C], 00000000 //[ebp+0C] points to the second string
- :0F00357E mov edi, 00000000
- :0F003583 je 0F00358B
- :0F003585 mov ecx, dword ptr [ebp+0C] // ECX = second string that is compared
- :0F003588 mov edi, dword ptr [ecx-04] // EDI = Length(second string)*2
- :0F00358B cmp edi, esi // compare stringlength of both strings
- :0F00358D mov ebx, edi // save lenght of second string in EBX
- :0F00358F jnb 0F0035B6 // if string two has less chars, then string one, then jump
- :0F003591 cmp dword ptr [ebp+08], 00000000
- :0F003595 jne 0F0035CD
- :0F003597 test ebx, ebx
- :0F003599 je 0F0035C3
- :0F00359B mov eax, ebx
- :0F00359D shr eax, 1
- :0F00359F push eax
- :0F0035A0 push [ebp+0C] // points to second string
- :0F0035A3 push [ebp+10] // points to first string
- :0F0035A6 call MSVBVM50.0F00D9EA // this one compares them "really" and sets flag
- :0F0035AB test eax, eax // if they are the same
- :0F0035AD je 0F0035BA // then jump
- :0F0035AF pop edi // else return from call with "Not same" flag
- :0F0035B0 pop esi
- :0F0035B1 pop ebx
- :0F0035B2 pop ebp
- :0F0035B3 ret 000C
- :0F0035B6 mov ebx, esi
- :0F0035B8 jmp MSVBVM50.0F003591
-
- Here is the call at :F0035A6 that compares the two strings really.
-
- :0F00D9EA push esi // save esi
- :0F00D9EB push edi // save edi
- :0F00D9EC mov edi, dword ptr [esp+10] // edi = first string
- :0F00D9F0 mov esi, dword ptr [esp+0C] // esi = second string
- :0F00D9F4 mov ecx, dword ptr [esp+14] // ecx = length of both strings
- :0F00D9F8 xor eax, eax // erase eax
- :0F00D9FA repz // this one
- :0F00D9FB cmpsw // compares them
- :0F00D9FD je 0F00DA04 // if they are equal, then jump
- :0F00D9FF sbb eax, eax // else
- :0F00DA01 sbb eax, FFFFFFFF // set "not equal" flag
- :0F00DA04 pop edi // restore edi
- :0F00DA05 pop esi // restore esi
- :0F00DA06 ret 000C // return from call
-
- What do I want to show you? Just that every standard comparison of two strings must pass
- this lines of code. So breakpointing with SICE at :0F00D9F4 would easily reveal which
- strings are compared.
-
- Another example: BuLLeT's CrackMe 2.75:
- In this CrackMe we have no __vbaStrCmp :( - The important call is __vbaVarTstEq. The second
- appearance is the correct here, too. After some tracing (enter every callyou come - Yeah
- guess where you come. You will come to __vbaStrComp() again and then to the passage
- described above where the two strings are compared.
-
- :0F00D9EC mov edi, dword ptr [esp+10] // edi = real serial
- :0F00D9F0 mov esi, dword ptr [esp+0C] // esi = serial, you entered
-
- Just as I said: No matter which method of comparison is used by the programmer, this part
- of code will always be executed. One string will always be in esi, the other one will always
- be in edi.
-
- btw: I nearly forgot
- The serial for the first CrackMe is 2hard4u2crackm8
- The serial for the second CrackMe is 2rK4HJ4-7n8RgT09IW6a7kSlg33
-
- Attention: Remember that strings in VB are stored in "Wide char" format like this:
-
- [edi+00000000] - 00720032 2.r.
- [edi+00000004] - 0034004b K.4.
- [edi+00000008] - 004a0048 H.J.
- [edi+0000000C] - 002d0034 4.-.
- [edi+00000010] - 006e0037 7.n.
- [edi+00000014] - 00520038 8.R.
- [edi+00000018] - 00540067 g.T.
- [edi+0000001C] - 00390030 0.9.
- [edi+00000020] - 00570049 I.W.
- [edi+00000024] - 00610036 6.a.
- [edi+00000028] - 006b0037 7.k.
- [edi+0000002C] - 006c0053 S.l.
- [edi+00000030] - 00330067 g.3.
- [edi+00000034] - 00000033 3...
-
- Just get rid of every 00h and you will get the serial.
- Farthermore the wide char format is the reason, that not the "real" length of the strings
- is compared, but length*2.
-
-
- Eh, do I still hear doubts in your voice? Just CrackMes? Small deadlisting? I had luck?
- May a crack for a "real" program convince you? OK, here it comes. The target is Audio
- List Maker 1.52.1016. The EXE file is 355 KB big, the deadlisting is 6445KB. I hope that
- satisfies you. There are quite many __vbaStrCmp in the listing, but that shouldn't frighten
- us. With some *zen* we can easily eliminate most. When you enter a wrong serial, a
- messagebox appears. I believe that there's a messagebox when you enter a correct serial,
- too. Now it's only speculation, but we will later see, that it is indeed so. So look at
- the __vbaStrCmp calls and you will soon find this one:
-
- :0044877B 8B55E4 mov edx, dword ptr [ebp-1C] ;; point to real serial
- :0044877E 8B45D8 mov eax, dword ptr [ebp-28] ;; point to entered serial
- :00448781 52 push edx ;; save real serial to stack
- :00448782 50 push eax ;; save entered serial to stack
-
- * Reference To: MSVBVM50.__vbaStrCmp, Ord:0000h
- |
- :00448783 FF1540824500 Call dword ptr [00458240] ;; compare them and set flag
- :00448789 85C0 test eax, eax ;; test flag
- :0044878B 0F85B6050000 jne 00448D47 ;; if not set, then jump to "beggar off"
-
- I strongly believed that this one is "our" __vbaStrCmp, as there is a conditioned jump right
- after the call that jumps to a MessageBox (MSVBVM50.rtcMsgBox). If the jump is not taken,
- a messagebox will appear, too. Read the real serial out at :0044877B. For LaZaRuS it is
- ALM4-3111-7951-9X2K where the "-" mustn't be entered in the program as there are only 16
- chars allowed.
-
- Alright, I know what you are saying. When the serials are pushed in front of the __vbaStrCmp
- why did we trace into the call in the two CrackMes??? Imagine that there are some ways
- to hide the __vbaStrCmp in the deadlisting (for example: call edi - the indirect call
- through a register). In a deadlisting there won't be much chances to find that, but if you
- put a breakpoint on the correct place inside the __vbaStrComp() function you can easily find
- the addresses that call the __vbaStrCmp with the help of SICE.
-
-
- III. BTW
-
- Greets to: tKC, Ed!son, Moral Insanity, +Sandman, Fravia+ and everyone at #cracking4newbies,
- +Sandman's forum and Fravia+'s forum.
-
- IV. All tutorials by LaZaRuS
-
-